package org.simplesocket.simplenettymtbatis.datasource;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.simplesocket.simplenettycore.context.SimpleNettyContext;
import org.simplesocket.simplenettycore.utils.CommonUtils;
import org.simplesocket.simplenettymtbatis.SimpleNettyMybatisConfig;
import org.simplesocket.simplenettymtbatis.config.MybatisConfig;

import java.io.IOException;
import java.io.InputStream;

@Slf4j
public class Database {
        
        private static Database databaseContext;
        
        private final SqlSessionFactory sqlSessionFactory;
        
        private static DruidDataSource dataSource;
        
        private Database(SimpleNettyContext simpleNettyContext,SimpleNettyMybatisConfig config) {
            log.info("Create sqlSessionFactory ...");
            
            if (StrUtil.isNotBlank(config.getConfigFile())){
                log.info("Load mybatis configure file ...");
                try {
                    InputStream inputStream = Resources.getResourceAsStream(config.getConfigFile());
                    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                }catch (Exception e){
                    log.error("Failed to load mybatis config file,because:\n");
                    CommonUtils.printException(e);
                    System.exit(-1);
                    throw new RuntimeException();
                }
            }else {
                log.info("Load mybatis configure object ...");
                try {
                    MybatisConfig configObject = config.getConfigObject();
                    sqlSessionFactory = configObject.getSqlSessionFactory(simpleNettyContext);
                }catch (Exception e){
                    log.error("Failed to load mybatis config object,because:\n");
                    CommonUtils.printException(e);
                    System.exit(-1);
                    throw new RuntimeException();
                }
            }
            
            dataSource = (DruidDataSource) sqlSessionFactory.getConfiguration()
                    .getEnvironment()
                    .getDataSource();
            log.info("Success to create sqlSessionFactory ...");
        }
        
        public static Database init(SimpleNettyContext simpleNettyContext,
                                    SimpleNettyMybatisConfig config) throws IOException {
            if (databaseContext == null){
                log.info("Preparing to init database ...");
                databaseContext = new Database(simpleNettyContext,config);
                log.info("Init database successfully ...");
            }
            
            return databaseContext;
        }
        
        public SqlSession sqlSession(){
            return sqlSessionFactory.openSession(ExecutorType.SIMPLE,true);
        }

        public String poolStatus() {
            if (dataSource != null) {
                return "活跃连接数: " + dataSource.getActiveCount() +
                        "\n空闲连接数: " + dataSource.getPoolingCount() +
                        "\n总连接数: " + (dataSource.getPoolingCount() + dataSource.getActiveCount());
            }
            return "连接池未初始化";
        }
        
        public void closeDataSource() {
            if (dataSource != null && !dataSource.isClosed()) {
                dataSource.close();
            }
        }
        
    }